package genedit.model;

import genedit.gui.GProjectTree;

import java.util.Date;
import java.util.Enumeration;

import javax.swing.SwingUtilities;

/**
 * Klasa za generičke dokumenta. Klase naslednice treba da se povežu sa tipom
 * elementa koji obrađuju.
 * 
 * @author Nikola
 * @version 1.2 18/12/2013
 */
public abstract class Document extends HierarchyElement {

	private static final long serialVersionUID = 1L;

	/**
	 * Brojač za generisanje podrazumevanog imena dece ovog čvora.
	 */
	private int elementCount = 0;

	/**
	 * Referenca na roditeljski čvor.
	 */
	protected HierarchyElement parent = null;

	/**
	 * Ime dokumenta.
	 */
	protected String name;

	/**
	 * Tip dokumenta. U opšte slučaju određuje koja vrsta elementa je dozvoljena
	 * na datom dijagramu.
	 */
	protected String type;

	/**
	 * Ime autora dokumenta.
	 */
	protected String author;

	/**
	 * Datum kreiranja dokumenta.
	 */
	protected Date dateCreated;

	/**
	 * Datum poslednje izmene dokumenta.
	 */
	protected Date dateLastModified;

	protected java.util.Collection<Document> subDocument;
	protected Document parentDocument;

	// Potencijalno uklanjanje.
	protected boolean isSaved;

	public Document(HierarchyElement parent) {
		super();
		this.parent = parent;
	}

	public Document(HierarchyElement parent, String name) {
		super();
		this.parent = parent;
		this.name = name;
	}

	public HierarchyElement getParent() {
		return parent;
	}

	public String getName() {
		return name;
	}

	public String getType() {
		return type;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String newAuthor) {
		author = newAuthor;
	}

	public Date getDateCreated() {
		return dateCreated;
	}

	public Date getDateLastModified() {
		return dateLastModified;
	}

	@Override
	public boolean isSaved() {
		return isSaved;
	}

	@Override
	public void setSaved(boolean saved) {
		this.isSaved = saved;
	}

	@Override
	public boolean getAllowsChildren() {
		return true;
	}

	@Override
	public boolean isLeaf() {
		return false;
	}

	public String toString() {
		return name;
	}

	public int getElementCount() {
		return ++elementCount;
	}

	public void setElementCount(int elementCount) {
		this.elementCount = elementCount;
	}

	public java.util.Collection<Document> getSubDocument() {
		if (subDocument == null)
			subDocument = new java.util.HashSet<Document>();
		return subDocument;
	}

	public java.util.Iterator<Document> getIteratorSubDocument() {
		if (subDocument == null)
			subDocument = new java.util.HashSet<Document>();
		return subDocument.iterator();
	}

	public void setSubDocument(java.util.Collection<Document> newSubDocument) {
		removeAllSubDocument();
		for (java.util.Iterator<Document> iter = newSubDocument.iterator(); iter.hasNext();)
			addSubDocument((Document) iter.next());
	}

	public void addSubDocument(Document newDocument) {
		if (newDocument == null)
			return;
		if (this.subDocument == null)
			this.subDocument = new java.util.HashSet<Document>();
		if (!this.subDocument.contains(newDocument)) {
			this.subDocument.add(newDocument);
			newDocument.setParentDocument(this);
		}
		SwingUtilities.updateComponentTreeUI(GProjectTree.getInstance().getTree());
		getObservable().setChanged();
		getObservable().notifyObservers();
	}

	public void removeSubDocument(Document oldDocument) {
		if (oldDocument == null)
			return;
		if (this.subDocument != null)
			if (this.subDocument.contains(oldDocument)) {
				this.subDocument.remove(oldDocument);
				oldDocument.setParentDocument((Document) null);
			}
		SwingUtilities.updateComponentTreeUI(GProjectTree.getInstance().getTree());
	}

	public void removeAllSubDocument() {
		if (subDocument != null) {
			Document oldDocument;
			for (java.util.Iterator<Document> iter = getIteratorSubDocument(); iter.hasNext();) {
				oldDocument = (Document) iter.next();
				iter.remove();
				oldDocument.setParentDocument((Document) null);
			}
		}
	}

	public Document getParentDocument() {
		return parentDocument;
	}

	public void setParentDocument(Document newDocument) {
		if (this.parentDocument == null || !this.parentDocument.equals(newDocument)) {
			if (this.parentDocument != null) {
				Document oldDocument = this.parentDocument;
				this.parentDocument = null;
				oldDocument.removeSubDocument(this);
			}
			if (newDocument != null) {
				this.parentDocument = newDocument;
				this.parentDocument.addSubDocument(this);
			}
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public Enumeration children() {
		return (Enumeration<HierarchyElement>) subDocument;
	}
}